/*************************************************************************
 * @file: loop.cpp
 * @date: 01/04/2012
 * TOPOL v1_0 - (c)copyright 2012 TEC/UFF
 *************************************************************************
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 ************************************************************************/

// includes
//----------
#include "loop.h"
#include "face.h"
#include "halfedge.h"
#include "vertex.h"
#include "ipoint.h"
#include <iostream>


///////////////////////////////////////////////////
///  Constructor and Destructor Implementation  ///
///////////////////////////////////////////////////

//-------------------------------------------------------------------------
Loop::Loop( Face* _f )
: m_prevl( NULL )
, m_nextl( _f->getFloops() )
, m_ledg( NULL )
, m_lface( NULL )
{
	Loop* loopOfFace = _f->getFloops();
	if( loopOfFace )
	{
    loopOfFace->m_prevl = this;
	}
	_f->setLoop( this );
	m_lface = _f;
}
//-------------------------------------------------------------------------

//-------------------------------------------------------------------------
Loop::~Loop()
{
  if( this->m_prevl )
    this->m_prevl->m_nextl = this->m_nextl;
  if( this->m_nextl )
    this->m_nextl->m_prevl = this->m_prevl;
  if(this == m_lface->getFloops())
    m_lface->setLoop( this->m_nextl );
}
//-------------------------------------------------------------------------



///////////////////////////////////////
///  PUBLIC Methods Implementation  ///
///////////////////////////////////////

//-------------------------------------------------------------------------
Loop* 
Loop::getPrevLoop()
{
  return m_prevl;
}
//-------------------------------------------------------------------------

//-------------------------------------------------------------------------
Loop* 
Loop::getNextl()
{
	return m_nextl;
}
//-------------------------------------------------------------------------

//-------------------------------------------------------------------------
Face* 
Loop::getFace()
{
	return m_lface;
}
//-------------------------------------------------------------------------

//-------------------------------------------------------------------------
HalfEdge* 
Loop::getLedg()
{
	return m_ledg;
}
//-------------------------------------------------------------------------

//-------------------------------------------------------------------------
double 
Loop::getArea()
{
  //std::cout << "--------AREA--------" << std::endl;
  //std::cout << ".F = " << m_lface->getFaceno() << std::endl;
  double area=0.0;
  HalfEdge* h = m_ledg;
  do
  {
    //std::cout << ".V = " << h->getVtx()->getVertexno() << std::endl;
    IPoint* pti  = h->getVtx()->getPoint();
    IPoint* ptii = h->getNxt()->getVtx()->getPoint();
    double xi = pti->getX();
    double yi = pti->getY();
    double xii = ptii->getX();
    double yii = ptii->getY();
    area += (xi*yii - xii*yi);
  }
  while((h = h->getNxt()) != m_ledg );
  area = area / 2.0;
  //std::cout << "AREA = " << area << std::endl;
  return area;
}
//-------------------------------------------------------------------------

//-------------------------------------------------------------------------
void 
Loop::getCenter( double& _xc, double& _yc, double& _zc )
{
  //std::cout << "--------CENTER--------" << std::endl;
  //std::cout << ".F = " << m_lface->getFaceno() << std::endl;
  double area= this->getArea();
  _xc = 0;
  _yc = 0;
  HalfEdge* h = m_ledg;
  do
  {
    IPoint* pti  = h->getVtx()->getPoint();
    IPoint* ptii = h->getNxt()->getVtx()->getPoint();
    double xi = pti->getX();
    double yi = pti->getY();
    double xii = ptii->getX();
    double yii = ptii->getY();
    _xc += (xi+xii)*(xi*yii - xii*yi);
    _yc += (yi+yii)*(xi*yii - xii*yi);
  }
  while((h = h->getNxt()) != m_ledg );
  _xc = _xc/(6.0*area);
  _yc = _yc/(6.0*area);
}
//-------------------------------------------------------------------------


//-------------------------------------------------------------------------
void  
Loop::getMonentOfInertia( double& _Ixx, double& _Iyy, double& _Ixy )
{
  _Ixx = 0;
  _Iyy = 0;
  _Ixy = 0;
  double factor;
  double xi = 0.0; double xii = 0.0;
  double yi = 0.0; double yii = 0.0;
  //std::cout << "--------CENTER--------" << std::endl;
  //std::cout << ".F = " << m_lface->getFaceno() << std::endl;
  HalfEdge* h = m_ledg;
  do
  {
    IPoint* pti  = h->getVtx()->getPoint();
    IPoint* ptii = h->getNxt()->getVtx()->getPoint();
    double xi = pti->getX();
    double yi = pti->getY();
    double xii = ptii->getX();
    double yii = ptii->getY();
    factor = yii*yii*( xi + 3*xii ) + 2*yi*yii*( xi + xii ) + yi*yi*( 3*xi + xii );
    _Ixx = _Ixx + (yii-yi)*factor/12.0;
    _Ixy = _Ixy + (xi-xii)*factor/24.0;
    factor = xii*xii*( yi + 3*yii ) + 2*xi*xii*( yi + yii ) + xi*xi*( 3*yi + yii );
    _Iyy = _Iyy + (xi-xii)*factor/12.0;
  }
  while((h = h->getNxt()) != m_ledg );
}
//-------------------------------------------------------------------------



//-------------------------------------------------------------------------
void 
Loop::setLedg( HalfEdge* _newhe )
{
  m_ledg = _newhe;
}
//-------------------------------------------------------------------------


//-------------------------------------------------------------------------
void 
Loop::setPrv( Loop* _l )
{
  m_prevl = _l;
}
//-------------------------------------------------------------------------

//-------------------------------------------------------------------------
void 
Loop::setNxt( Loop* _l )
{
  m_nextl = _l;
}
//-------------------------------------------------------------------------


//-------------------------------------------------------------------------
void 
Loop::setLFace( Face* _f )
{
  m_lface = _f;
}
//-------------------------------------------------------------------------
